import java.util.ArrayList;
/**
 *	Method 抽象类，包括各种函数，如求平均值等
 */
public abstract class Method {

	protected String name = null;		// 方法的名称
	protected int format = 0;			// 数据小数点后的位数
	protected ArrayList<Float> blackList = new ArrayList<Float>();	// 记录粗大误差的黑名单
	protected ArrayList<Float> data = new ArrayList<Float>();		// 记录的测量数据

	protected abstract boolean hasGrossError();	// 判断是否含有粗大误差的抽象函数

	/**
	 *	构造函数
	 */
	public Method(ArrayList<Float> data, int format) {
		this.data.addAll(data);
		this.format = format;
	}
	
	/**
	 *	主要的方法，如果上一次判断含有粗大误差，则去掉误差后继续判断，知道没有粗大误差为止
	 */
	public void check() {
		while (hasGrossError()) {
			data.removeAll(blackList);
		}
		show();
	}
	
	/**
	 *	计算残余误差
	 */
	protected ArrayList<Float> calV(ArrayList<Float> data) {
		ArrayList<Float> v = new ArrayList<Float>();
		float avarage = calAvarage(data);
		for (Float next : data) {
			v.add(next - avarage);
		}
		return v;
	}

	/**
	 *	计算标准差
	 */
	protected final float calSigma(ArrayList<Float> data) {
		float sumV2 = 0;
		float avarage = calAvarage(data);
		for (Float next : data) {
			sumV2 += (next - avarage) * (next - avarage);
		}
		return (float) Math.sqrt(sumV2 / (data.size() - 1));
	}
	
	/**
	 *	计算平均值
	 */
	protected final float calAvarage(ArrayList<Float> data) {
		float sum = 0;
		for (Float next : data) {
			sum += next;
		}
		return sum / data.size();
	}

	/**
	 *	显示计算结果
	 */
	public final void show() {
		System.out.println("使用" + name + "判断结果如下:");
		if (blackList.size() == 0) {
			System.out.print("不存在粗大误差！");
		} else {
			System.out.print("存在" + blackList.size() + "个含有粗大误差的测量值，为：");
			for (int i = 0; i < blackList.size(); i++) {
				if (i != blackList.size() - 1) {
					System.out.printf("%." + format + "f、", blackList.get(i));
				} else {
					System.out.printf("%." + format + "f。", blackList.get(i));
				}
			}
		}
		System.out.println("\n");
	}
}
